// Datapump that returns a streambuf for a file URL
// Copyright 2006 (C) Ralph Thomas

#include <datapumps/streambuf.h>
#include <ui/array_datapump_adapter.h>
#include <iostream>
#include <fstream>
#include <boost/shared_ptr.hpp>
#include <stdexcept>
#include <toolkit/application.h>

namespace datapumps {
    typedef boost::shared_ptr<std::streambuf> shared_streambuf_t;
    typedef app::array_datapump_adapter_t<shared_streambuf_t (const std::string&)> super;
    struct monitored_streambuf_t : public super {
        toolkit::monitor_connection_t   file_monitor_m;
        std::string                     last_m;
        
        monitored_streambuf_t(adobe::sheet_t& sheet, const adobe::array_t& array) : super( sheet, array ) {
            set_function( boost::bind( &monitored_streambuf_t::get_streambuf, this, _1 ) );
        }

        shared_streambuf_t get_streambuf(const std::string& url) {
            if (url.find("file://") == std::string::npos)
                throw std::runtime_error( "streambuf datapump: not a file URL: " + url );
            //
            // Monitor this file so that we can invalidate the datapump
            //
            if (url != last_m) file_monitor_m = toolkit::application::getInstance().monitor( url, boost::bind( &monitored_streambuf_t::changed, this, _1 ), false );
            last_m = url;
            std::string filename = url.substr(7, std::string::npos);
            //
            // Open this file. Note that sbuf == fbuf, so there's no memory
            // leak here.
            //
            std::filebuf* fbuf = new std::filebuf();
            std::streambuf* sbuf = fbuf->open( filename.c_str(), std::ios_base::in | std::ios_base::binary );
            if (sbuf) return shared_streambuf_t(sbuf);
            return shared_streambuf_t();
        }
        void changed( const std::string& url ) { update(); }
    };
    adobe::any_regular_t make_streambuf_datapump( const adobe::array_t& array, adobe::sheet_t& sheet ) {
        return adobe::any_regular_t( adobe::binder_ptr_t( new monitored_streambuf_t( sheet, array ) ) );
    }
}
